﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Serial_assistant
{
    public delegate void ShowWindow();
    public delegate void HideWindow();
    public delegate void OpenPort();
    public delegate void ClosePort();
    public delegate Point GetMainPos();
    public delegate int GetMainWidth();
    public partial class Form1 : Form
    {
        GPS gps;                        //创建gps窗口对象
        BMaps bmap;                     //创建百度地图窗口对象
        Oscilloscope display;           //创建波形显示窗口对象
        int flag = 0, skim = 2, skim_num = 11;
        
        bool ishide = false;
        public Form1()
        {
            InitializeComponent();
            serialPort1.Encoding = Encoding.GetEncoding("GB2312");
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void label4_Click(object sender, EventArgs e)
        {

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 1; i < 20; i++)
            {
                comboBox1.Items.Add("COM" + i.ToString());                                        //添加串口
            }
            comboBox1.Text = "COM3";                                                              //默认选项
            comboBox2.Text = "9600";
            textBox1.Visible = false;
            button6.Visible = false;
            radioButton2.Checked = true;
            radioButton4.Checked = true;
            button1.Text = "打开端口";
            this.BackgroundImage = Properties.Resources.pict1;
            this.BackgroundImageLayout = ImageLayout.Stretch;
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            if (!radioButton3.Checked)
            {
                string s = serialPort1.ReadExisting();
                Double longitude, latitude;
                Double altitude, speed;
                string[] sArray;
                textBox1.AppendText(s);                                //串口类会自动处理汉字，所以不需要特别转换
                if (display != null && (gps == null || gps.IsDisposed))
                {
                    try
                    {
                        display.AddData(Convert.ToDouble(s));
                    }
                    catch
                    {
                             
                    }
                }
                if((gps != null || bmap != null) && (display == null || display.IsDisposed))
                {
                    try
                    {
                        if(gps != null && !gps.IsDisposed)
                        {
                            //与单片机发送数据协议一致，采用"_"进行分割
                            sArray = s.Split('_');

                            //获得经纬度数据
                            longitude = Convert.ToDouble(sArray[0]) / 100000;
                            latitude = Convert.ToDouble(sArray[1]) / 100000;

                            //获得海拔高度和速度数据
                            altitude = Convert.ToDouble(sArray[4]) / 10;
                            speed = Convert.ToDouble(sArray[5]) / 1000;

                            //将数据传输至gps对象中进行绘制
                            gps.Add_longitude(longitude);
                            gps.Add_latitude(latitude);
                            gps.jingdu = longitude.ToString();
                            gps.weidu = latitude.ToString();
                            gps.ewhemi = sArray[2];
                            gps.nshemi = sArray[3];
                            gps.altitude = altitude.ToString();
                            gps.speed = speed.ToString();
                        }
                        if(bmap != null && !bmap.IsDisposed)
                        {
                            //与单片机发送数据协议一致，采用"_"进行分割
                            sArray = s.Split('_');

                            //获得经纬度数据
                            longitude = Convert.ToDouble(sArray[0]) / 100000;
                            latitude = Convert.ToDouble(sArray[1]) / 100000;

                            //获得海拔高度和速度数据
                            altitude = Convert.ToDouble(sArray[4]) / 10;
                            speed = Convert.ToDouble(sArray[5]) / 1000;

                            //初始化上一时刻位置防止出错
                            if (bmap.isfirst)
                            {
                                bmap.pre_longitude = longitude;
                                bmap.pre_latitude = latitude;
                                bmap.isfirst = false;
                            }

                            bmap.longitude = longitude;
                            bmap.latitude = latitude;
                            try
                            {
                                bmap.show_location(longitude, sArray[2], latitude, sArray[3], altitude, speed);
                            }
                            catch { }
                        }
                    }
                    catch
                    {
                    }
                }
            }
            else
            {
                try
                {
                    byte[] data = new byte[serialPort1.BytesToRead];                                //定义缓冲区，因为串口事件触发时有可能收到不止一个字节
                    serialPort1.Read(data, 0, data.Length);
                    foreach (byte Member in data)                                                   //遍历用法
                    {
                        string str = Convert.ToString(Member, 10);
                        textBox1.AppendText(str);
                    }
                }
                catch { }
            }
        }


        private void button1_Click(object sender, EventArgs e)
        {
            if(flag == 0)
            {
                try
                {
                    serialPort1.PortName = comboBox1.Text;                                              //端口号
                    serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);                             //波特率
                    serialPort1.Open();                                                                 //打开串口
                }
                catch
                {
                    MessageBox.Show("端口错误", "错误");
                }
                button1.Text = "关闭端口";
                flag = 1;
            }
            else
            {
                try
                {
                    serialPort1.Close();                                                            //关闭串口        
                }
                catch
                {

                }
                button1.Text = "打开端口";
                flag = 0;
            }
        
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[1];                                                         //单字节发数据     
            if (serialPort1.IsOpen)
            {
                if (textBox2.Text != "")
                {
                    if (!radioButton1.Checked)
                    {
                        try
                        {
                            serialPort1.Write(textBox2.Text);
                            //serialPort1.WriteLine();                             //字符串写入
                        }
                        catch
                        {
                            MessageBox.Show("串口数据写入错误", "错误");
                        }
                    }
                    else                                                                    //数据模式
                    {
                        try                                                                 //如果此时用户输入字符串中含有非法字符（字母，汉字，符号等等，try，catch块可以捕捉并提示）
                        {
                            for (int i = 0; i < (textBox2.Text.Length - textBox2.Text.Length % 2) / 2; i++)//转换偶数个
                            {
                                Data[0] = Convert.ToByte(textBox2.Text.Substring(i * 2, 2), 10);           //转换
                                serialPort1.Write(Data, 0, 1);
                            }
                            if (textBox2.Text.Length % 2 != 0)
                            {
                                Data[0] = Convert.ToByte(textBox2.Text.Substring(textBox2.Text.Length - 1, 1), 10);//单独处理最后一个字符
                                serialPort1.Write(Data, 0, 1);                              //写入
                            }
                        }
                        catch
                        {
                            MessageBox.Show("数据转换错误，请输入数字。", "错误");
                        }
                    }
                }
            }
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void panel2_Paint(object sender, PaintEventArgs e)
        {

        }

        public void ClosePort()//关闭串口，供委托调用
        {
            try
            {
                serialPort1.Close();
            }
            catch (System.Exception)
            {

            }
        }

        private Point GetMyPos()//供委托调用
        {
            return this.Location;
        }

        public void OpenPort()//打开串口，供委托调用
        {
            try
            {
                serialPort1.Open();
            }
            catch (System.Exception)
            {
                MessageBox.Show("串口打开失败，请检查", "错误");
            }
        }
        public void ShowMe()//供委托调用
        {
            this.Show();
        }
        public void HideMe()//供委托调用
        {
            this.Hide();
        }

        //创建波形显示对象函数
        private void CreateNewDrawer()
        {
            display = new Oscilloscope();//创建新对象
            display.ShowMainWindow = new ShowWindow(ShowMe);//初始化类成员委托
            display.HideMainWindow = new HideWindow(HideMe);
            display.GetMainPos = new GetMainPos(GetMyPos);
            display.CloseSerialPort = new ClosePort(ClosePort);
            display.OpenSerialPort = new OpenPort(OpenPort);
            display.GetMainWidth = new GetMainWidth(GetMyWidth);
            display.Show();//显示窗口
        }

        //创建GPS显示对象函数
        private void CreateDrawGPS()
        {
            gps = new GPS();
            gps.ShowMainWindow = new ShowWindow(ShowMe);//初始化类成员委托
            gps.HideMainWindow = new HideWindow(HideMe);
            gps.GetMainPos = new GetMainPos(GetMyPos);
            gps.CloseSerialPort = new ClosePort(ClosePort);
            gps.OpenSerialPort = new OpenPort(OpenPort);
            gps.GetMainWidth = new GetMainWidth(GetMyWidth);
            gps.Show();//显示窗口
        }

        //创建地图显示对象函数
        private void CreateDrawBMaps()
        {
            bmap = new BMaps();
            bmap.ShowMainWindow = new ShowWindow(ShowMe);//初始化类成员委托
            bmap.HideMainWindow = new HideWindow(HideMe);
            bmap.GetMainPos = new GetMainPos(GetMyPos);
            bmap.CloseSerialPort = new ClosePort(ClosePort);
            bmap.OpenSerialPort = new OpenPort(OpenPort);
            bmap.GetMainWidth = new GetMainWidth(GetMyWidth);
            bmap.Show();//显示窗口
        }

        //创建波形显示窗口对象函数
        private void CreateDisplayer()
        {
            CreateNewDrawer();
            Rectangle Rect = Screen.GetWorkingArea(this);
            display.SetWindow(Rect.Width - this.Width, new Point(this.Width/2, this.Top/2));//设置绘制窗口宽度，以及坐标
        }

        //创建GPS显示窗口对象函数
        private void CreateGPS()
        {
            CreateDrawGPS();
            gps.SetWindow(new Point(this.Width/2, this.Top/2));//设置创建窗口坐标
        }

        //创建地图显示窗口对象函数
        private void CreatBMaps()
        {
            CreateDrawBMaps();
            bmap.SetWindow(new Point(this.Width / 2, this.Top / 2));//设置创建窗口坐标
        }

        int GetMyWidth()//供委托调用
        {
            return this.Width;
        }


        private void button4_Click(object sender, EventArgs e)
        {
            //逻辑判断----使波形显示窗口和GPS显示窗口不能同时打开，以免数据接收导致绘制异常
            if (display == null)//第一次创建Displayer = null
            {
                if (gps == null && bmap == null)
                {
                    CreateDisplayer();
                }
                else if (gps == null && bmap.IsDisposed)
                {
                    CreateDisplayer();
                }
                else if (gps.IsDisposed && bmap == null)
                {
                    CreateDisplayer();
                }
                else if(gps.IsDisposed && bmap.IsDisposed)
                {
                    CreateDisplayer();
                }
            }
            else
            {
                if (display.IsDisposed && (gps == null || gps.IsDisposed))//多次创建通过判断IsDisposed确定串口是否已关闭，避免多次创建
                {
                    CreateDisplayer();
                }
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            //逻辑判断----使波形显示窗口和GPS显示窗口不能同时打开，以免数据接收导致绘制异常
            if (gps == null)//第一次创建Displayer = null
            {
                if(display == null)
                {
                    CreateGPS();
                }
                else if(display.IsDisposed)
                {
                    CreateGPS();
                }
            }
            else
            {
                if (gps.IsDisposed && (display == null ||display.IsDisposed))//多次创建通过判断IsDisposed确定串口是否已关闭，避免多次创建
                {
                    CreateGPS();
                }
            }
        }

        
        private void button8_Click(object sender, EventArgs e)
        {
            //逻辑判断----使波形显示窗口和地图显示窗口不能同时打开，以免数据接收导致绘制异常
            if (bmap == null)//第一次创建Displayer = null
            {
                if (display == null)
                {
                    CreatBMaps();
                }
                else if (display.IsDisposed)
                {
                    CreatBMaps();
                }
            }
            else
            {
                if (bmap.IsDisposed && (display == null || display.IsDisposed))//多次创建通过判断IsDisposed确定串口是否已关闭，避免多次创建
                {
                    CreatBMaps();
                }
            }
        }


        //清空数据接收消息框函数
        private void button6_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
        }


        //收起数据接收消息框函数
        private void button2_Click(object sender, EventArgs e)
        {
            if (ishide)
            {
                //使数据接收消息框不可见
                textBox1.Visible = false;
                button6.Visible = false;
                ishide = false;
            }
            else
            {
                //使数据接收消息框可见
                textBox1.Visible = true;
                button6.Visible = true;
                ishide = true;
            }
        }

        //切换背景函数
        private void button5_Click(object sender, EventArgs e)
        {
            if (skim == 11)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict11;
            }
            if (skim == 10)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict10;
            }
            if (skim == 9)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict9;
            }
            if (skim == 8)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict8;
            }
            if (skim == 7)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict7;
            }
            if (skim == 6)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict6;
            }
            if (skim == 5)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict5;
            }
            if (skim == 4)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict4;
            }
            if (skim == 3)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict3;
            }
            if (skim == 2)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict2;
            }
            if (skim == 1)
            {
                skim++;
                this.BackgroundImage = Properties.Resources.pict1;
            }       
            if (skim == skim_num + 1)
            {
                skim = 1;
            }
        }
    }
}
